package com.shujia.jichu

/**
 * scala中的集合
 * List: 有序，可以发生重复
 * Set:  无序，且元素唯一
 * Map:  元素是键值对的格式存储的，键是唯一的
 * Tuple: 元组，长度是固定的
 *
 */
object Demo14List {
  def main(args: Array[String]): Unit = {
    /**
     * scala中的List: 有序，可以发生重复
     *
     * scala中的List是不可变的，长度是固定
     */
    //创建一个List集合对象
    //    val list1: List[Nothing] = List()
    val list1: List[Int] = List(88, 66, 22, 99, 11, 33, 110, 11, 22, 44, 22, 55, 11, 33)
    println(list1.size)
    println(list1.length)

    println(list1)
    //提供了很多java集合中没有的方法

    println("=" * 100)
    //通过下标索引获取元素
    println(list1(3))

    //获取第一个元素
    println(list1.head)

    //获取最后一个元素
    println(list1.last)

    //除去第一个元素以外的，返回新的集合
    println(list1.tail)
    println(list1)

    //使用分隔符拼接集合中的元素
    println(list1.mkString("|"))

    //将集合元素反转，返回新的集合存储
    println(list1.reverse)
    println(list1)

    //从左向右取n个元素，使用一个新的集合存储
    println(list1.take(4))

    //从右向左取n个元素，使用一个新的集合存储
    println(list1.takeRight(4))

    //takeWhile(p: Int => Boolean) 从第一个元素开始取，直到函数的返回值是false的时候
    println(list1.takeWhile(_ % 22 == 0))

    //去重集合中的元素，使用一个新的集合存储
    println(list1.distinct)

    //针对元素是Int的List，可以使用sum函数
    println(list1.sum)

    //获取元素最大值
    println(list1.max)

    //获取元素最小值
    println(list1.min)
    println("=" * 100)

    /**
     * 集合的遍历
     */
    for (elem <- list1) {
      println(elem)
    }
    println("=" * 100)

    /**
     * 函数式编程：
     * 高阶函数：foreach本身的作用是将集合中的元素取出来传递给后面的函数，在函数中进行处理
     */
    //    list1.foreach(println)
    //需求：对集合中的偶数元素进行求和
    var sum = 0
    list1.foreach((i: Int) => {
      if (i % 2 == 0) {
        sum += i
      }
    })
    println(s"集合中所有偶数元素的和为${sum}")
    println("=" * 100)
    /**
     * 高阶函数：map
     *
     */
    val list2: List[Int] = list1.map((i: Int) => {
      i + 100
    })
    println(s"list1: ${list1}")
    println(s"list2: ${list2}")
    println("=" * 100)
    //需求，集合中的元素偶数+100 奇数-100
    val list3: List[Int] = list1.map((i: Int) => {
      if (i % 2 == 0) {
        i + 100
      } else {
        i - 100
      }
    })
    println(s"list1: ${list1}")
    println(s"list2: ${list3}")

    /**
     * 高阶函数：
     * 循环集合，将集合中的每一个元素传入到后面的函数中，如果函数的结果式true，那么这个元素就会被添加到新集合中，否则就不添加
     * 新集合的结果就是过滤之后的结果
     */
    //过滤出元素是奇数的
    println(list1.filter((i: Int) => i % 2 == 1))
    println("=" * 100)
    /**
     * flatMap 效果类似于hive中的explode函数
     * 将集合中的每一个元素传入到后面的函数中，进行扁平化
     */
    val strList: List[String] = List("python|java|linux", "mysql|redis|clickhouse", "hadoop|hive|zookeeper")
    //需求：将每一个单词切分出来，得到每一个单词
    for (str <- strList) {
      val splitArray: Array[String] = str.split("\\|")
      for (word <- splitArray) {
        println(word)
      }
    }
    println("=" * 100)
    val list4: List[String] = strList.flatMap((line: String) => line.split("\\|"))
    println(s"list1: ${strList}")
    println(s"list4: ${list4}")
    println("=" * 100)

    /**
     * 高阶函数：排序函数
     * val list1: List[Int] = List(88, 66, 22, 99, 11, 33, 110,11, 22, 44, 22, 55, 11, 33)
     *
     * sortBy
     * 将集合中的每一个元素传入到后面的函数中，以指定的方式进行排序
     *
     */
    println(list1.sortBy((i: Int) => i)) // 默认以从小到大的顺序排序
    println(list1.sortWith((x: Int, y: Int) => y < x)) //指定两个元素之间的大小关系进行排序

    println("=" * 100)

    /**
     * 高阶函数：groupBy
     * 将集合中的每一个元素传入到后面的函数中，相同的元素为一组
     */
    val list5: List[String] = List("hello", "world", "java", "world", "java", "world", "java", "hello", "hello", "spark", "flink", "hello", "spark", "flink")
    val wordsMap: Map[String, List[String]] = list5.groupBy((s: String) => s)
    for (elem <- wordsMap) {
      println(elem)
    }

    /**
     * 这个函数在List的调用下，都会返回一个新的集合，不会在原有的List集合上进行修改，因为scala中的List集合是不可变的
     *  高阶函数：
     *  foreach: 处理集合中每一个元素，直接输出或者其他处理，没有返回值的，不会返回新的集合
     *  map: 处理集合中每一个元素，有返回值的，将处理后的结果使用新的集合存储
     *  filter: 过滤出符合条件的元素
     *  flatMap: 扁平化
     *  sortBy: 排序
     *  groupBy: 分组
     */

  }

}
